/*
 * @(#)StyledListCellRenderer.java 8/11/2005
 *
 * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
 */

package com.element.ui.list;

import com.element.plaf.UIDefaultsLookup;
import com.element.ui.label.StyledLabel;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.io.Serializable;


/**
 * A list cell renderer based on StyledLabel. To use it, you should make your cell renderer extending this one and
 * override {@link #customizeStyledLabel(JList, Object, int, boolean, boolean)} method. If your overridden
 * method, you can call setStyleRange() or setStyleRanges() based on the item value, if it is leaf etc information.
 */
public class StyledListCellRenderer<E> extends StyledLabel
		implements ListCellRenderer<E>, Serializable {

	protected static Border noFocusBorder;

	/**
	 * Constructs a default renderer object for an item in a list.
	 */
	public StyledListCellRenderer() {
		super();
		if (noFocusBorder == null) {
			noFocusBorder = new EmptyBorder(1, 1, 1, 1);
		}
		setOpaque(true);
		setBorder(noFocusBorder);
	}

	@Override
	public Component getListCellRendererComponent(JList<? extends E> list, E value, int index, boolean isSelected, boolean cellHasFocus) {
		applyComponentOrientation(list.getComponentOrientation());
		if (isSelected) {
			setBackground(list.getSelectionBackground());
			setForeground(list.getSelectionForeground());
		} else {
			setBackground(list.getBackground());
			setForeground(list.getForeground());
		}

		setIgnoreColorSettings(isSelected);
		customizeStyledLabel(list, value, index, isSelected, cellHasFocus);

		setEnabled(list.isEnabled());
		setFont(list.getFont());

		Border border = null;
		if (cellHasFocus) {
			if (isSelected) {
				border = UIDefaultsLookup.getBorder("List.focusSelectedCellHighlightBorder");
			}
			if (border == null) {
				border = UIDefaultsLookup.getBorder("List.focusCellHighlightBorder");
			}
		} else {
			border = noFocusBorder;
		}
		setBorder(border);

		return this;
	}

	/**
	 * Overrides this method to customize the styled label.
	 *
	 * @param list
	 * @param value
	 * @param index
	 * @param isSelected
	 * @param cellHasFocus
	 */
	protected void customizeStyledLabel(JList<? extends E> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
		clearStyleRanges();
		if (value instanceof Icon) {
			setIcon((Icon) value);
			setText("");
		} else {
			setIcon(null);
			setText((value == null) ? "" : value.toString());
		}
	}


	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 *
	 * @return <code>true</code> if the background is completely opaque and differs from the JList's background;
	 * <code>false</code> otherwise
	 * @since 1.5
	 */
	@Override
	public boolean isOpaque() {
		Color back = getBackground();
		Component p = getParent();
		if (p != null) {
			p = p.getParent();
		}
		// p should now be the JList.
		boolean colorMatch = (back != null) && (p != null) &&
				back.equals(p.getBackground()) &&
				p.isOpaque();
		return !colorMatch && super.isOpaque();
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 */
	@Override
	public void validate() {
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 *
	 * @since 1.5
	 */
	@Override
	public void invalidate() {
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 *
	 * @since 1.5
	 */
	@Override
	public void repaint() {
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 */
	@Override
	public void revalidate() {
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 */
	@Override
	public void repaint(long tm, int x, int y, int width, int height) {
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 */
	@Override
	public void repaint(Rectangle r) {
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 */
	@Override
	protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
		// Strings get interned...
		if (propertyName.equals("text"))
			super.firePropertyChange(propertyName, oldValue, newValue);
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 */
	@Override
	public void firePropertyChange(String propertyName, byte oldValue, byte newValue) {
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 */
	@Override
	public void firePropertyChange(String propertyName, char oldValue, char newValue) {
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 */
	@Override
	public void firePropertyChange(String propertyName, short oldValue, short newValue) {
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 */
	@Override
	public void firePropertyChange(String propertyName, int oldValue, int newValue) {
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 */
	@Override
	public void firePropertyChange(String propertyName, long oldValue, long newValue) {
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 */
	@Override
	public void firePropertyChange(String propertyName, float oldValue, float newValue) {
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 */
	@Override
	public void firePropertyChange(String propertyName, double oldValue, double newValue) {
	}

	/**
	 * Overridden for performance reasons. See the <a href="#override">Implementation Note</a> for more information.
	 */
	@Override
	public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
	}

	/**
	 * A subclass of DefaultListCellRenderer that implements UIResource. DefaultListCellRenderer doesn't implement
	 * UIResource directly so that applications can safely override the cellRenderer property with
	 * DefaultListCellRenderer subclasses.
	 * <p/>
	 * <strong>Warning:</strong> Serialized objects of this class will not be compatible with future Swing releases. The
	 * current serialization support is appropriate for short term storage or RMI between applications running the same
	 * version of Swing.  As of 1.4, support for long term storage of all JavaBeans<sup><font size="-2">TM</font></sup>
	 * has been added to the <code>java.beans</code> package. Please see {@link java.beans.XMLEncoder}.
	 */
	public class UIResource extends StyledListCellRenderer<E>
			implements javax.swing.plaf.UIResource {
	}

}
